/**
 * @fileOverview    缓存控制.
 * @author          shaozhe.ysz@alibabapictures.com
 * @since           2016.07.29
 */

const
    fs = require('fs'),
    debug = require('./debug'),
    CACHE_CONFIG = __dirname + '/../cache/cache.json',
    CACHE_DIR = __dirname + '/../cache/',
    RETRY_TIMES = 3,
    Alphabet = (()=>{
        var judge = /[a-zA-Z0-9]/;
        return [...Array(130).keys()].map(i=>String.fromCharCode(i)).filter(s=>judge.test(s));
    })();

var Cache = new function(){
    var hash = {},
        max = 0,
        RESET_COUNT = RETRY_TIMES;

    try{
        let data = JSON.parse(fs.readFileSync(CACHE_CONFIG,'utf-8'))||{};
        max = data.max||0;
        hash = data.hash||{};
    }catch(e){
        hash = {};
        max = 0;
    }

    //  @public
    this.sync = ()=>{
        let content = JSON.stringify({max,hash});
        fs.writeFile(CACHE_CONFIG,content,(err)=>{
            if(err){
                RESET_COUNT--;
                if(RESET_COUNT)this.sync();
            }else{
                RESET_COUNT = RETRY_TIMES;
            }
        })
    }
    this.sync();

    this.set = (key,fileStr) =>{
        if(!fileStr||hash[key])return;
        var id = getId();
        var retry = RETRY_TIMES;
        var write = ()=>{
            fs.writeFile(CACHE_DIR + id,fileStr,(err)=>{
                if(err){
                    retry--;
                    if(retry)write();
                }else{
                    hash[key] = id;
                    this.sync();
                }
            })
        }
        write();
    }

    this.get = (key) =>{
        return new Promise((resolve,reject)=>{
            var id = hash[key];
            if(id){
                fs.readFile(CACHE_DIR + id,'utf-8',(err,fileStr)=>{
                    if(err&&fileStr!=''){
                        reject(err||null);
                        delete hash[key];
                    }else{
                        resolve(fileStr);
                    }
                })
            }else{
                reject(null);
            }
        })
    }

    this.clear = ()=>{

        return new Promise((O,X)=>{
            fs.readdir(CACHE_DIR,(err,arr)=>{
                if(arr.length){
                    Promise.all(
                        arr.map(p=>new Promise((resolve,reject)=>{
                            fs.unlink(CACHE_DIR+p,err=>{
                                resolve();
                            })
                        })
                    ))
                    .then(O)
                    .catch(X)
                }else{
                    O();
                }
                
            })
        });
    }

    //  @private
    var getId = ()=>{
        var l = Alphabet.length,str='';
        var m = ++max;
        do{
            str += Alphabet[m%l];
            m = (m-m%l)/l;
        }while(m>0)

        return str;
    }
}

module.exports = Cache;